package org.karelun.rabbit.rcp;

import java.util.ArrayList;
import java.util.Collection;

import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;
import org.karelun.rabbit.bridge.ITransactionEditingDomainProvider;
import org.karelun.rabbit.bridge.ui.action.RabbitCreateChildAction;
import org.karelun.rabbit.bridge.ui.action.RabbitCreateSiblingAction;
import org.karelun.rabbit.bridge.ui.action.RabbitEditorActionBarContributor;

public class EMFDiagramActionBarContributor extends
		RabbitEditorActionBarContributor implements ISelectionChangedListener {

	private IAction showPropertiesViewAction =new Action("Show Properties"){
		public void run() {
			try {
				getPage().showView("org.eclipse.ui.views.PropertySheet");
			} catch (PartInitException e) {
				e.printStackTrace();
			}
		}
	};
	
	private Collection<IAction> createChildActions;

	private Collection<IAction> createSiblingActions;

	private IEditorPart activeEditorPart;

	private ISelectionProvider selectionProvider;
	
	@Override
	protected void addGlobalActions(IMenuManager manager) {
		manager.insertAfter("additions-end", new Separator("ui-actions"));
		manager.insertAfter("ui-actions", showPropertiesViewAction);
		super.addGlobalActions(manager);
	}

	@Override
	public void menuAboutToShow(IMenuManager menuManager) {
		super.menuAboutToShow(menuManager);

		MenuManager submenuManager = new MenuManager("Child");
		populateManager(submenuManager, createChildActions, null);
		menuManager.insertBefore("edit", submenuManager);

		submenuManager = new MenuManager("Sibling");
		populateManager(submenuManager, createSiblingActions, null);
		menuManager.insertBefore("edit", submenuManager);
	}
	
	@Override
	public void setActiveEditor(IEditorPart part) {
		super.setActiveEditor(part);
		activeEditorPart = part;

	    // Switch to the new selection provider.
	    //
	    if (selectionProvider != null)
	    {
	      selectionProvider.removeSelectionChangedListener(this);
	    }
	    if (part == null)
	    {
	      selectionProvider = null;
	    }
	    else
	    {
	      selectionProvider = part.getSite().getSelectionProvider();
	      selectionProvider.addSelectionChangedListener(this);

	      // Fake a selection changed event to update the menus.
	      //
	      if (selectionProvider.getSelection() != null)
	      {
	        selectionChanged(new SelectionChangedEvent(selectionProvider, selectionProvider.getSelection()));
	      }
	    }
	    update();
	}

	@Override
	public void selectionChanged(SelectionChangedEvent event) {
		Collection<?> newChildDescriptors = null;
		Collection<?> newSiblingDescriptors = null;

		ISelection selection = event.getSelection();
		if (selection instanceof IStructuredSelection
				&& ((IStructuredSelection) selection).size() == 1) {
			Object object = ((IStructuredSelection) selection)
					.getFirstElement();

			EditingDomain domain = ((ITransactionEditingDomainProvider) activeEditorPart).getTransactionEditingDomain();

			newChildDescriptors = domain.getNewChildDescriptors(object, null);
			newSiblingDescriptors = domain.getNewChildDescriptors(null, object);
		}

		// Generate actions for selection; populate and redraw the menus.
		//
		createChildActions = generateCreateChildActions(newChildDescriptors,
				selection);
		createSiblingActions = generateCreateSiblingActions(
				newSiblingDescriptors, selection);
	}

	private Collection<IAction> generateCreateChildActions(
			Collection<?> descriptors, ISelection selection) {
		Collection<IAction> actions = new ArrayList<IAction>();
		if (descriptors != null) {
			for (Object descriptor : descriptors) {
				actions.add(new RabbitCreateChildAction(activeEditor, selection,
						descriptor));
			}
		}
		return actions;
	}

	private Collection<IAction> generateCreateSiblingActions(
			Collection<?> descriptors, ISelection selection) {
		Collection<IAction> actions = new ArrayList<IAction>();
		if (descriptors != null) {
			for (Object descriptor : descriptors) {
				actions.add(new RabbitCreateSiblingAction(activeEditor,
						selection, descriptor));
			}
		}
		return actions;
	}

	private void populateManager(IContributionManager manager,
			Collection<? extends IAction> actions, String contributionID) {
		if (actions != null) {
			for (IAction action : actions) {
				if (contributionID != null) {
					manager.insertBefore(contributionID, action);
				} else {
					manager.add(action);
				}
			}
		}
	}
	
	@Override
	protected boolean removeAllReferencesOnDelete() {
		return true;
	}

}
